/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once

#include "npobject.h"
#include "image_acquisition_model.h"
#include "plugin_model.h"
#include "list.h"


class _Plugin;

class NPObjectBase : public NPObjectAdapter
{
public:

    NPObjectBase( NPP npp )
        : NPObjectAdapter( npp )
    {
        m_pPlugin = ( _Plugin* ) npp->pdata;
    }

    virtual ~NPObjectBase() { }

    _Plugin* m_pPlugin;
};


class ScriptableDevice : public NPObjectBase, public DisposeEventHandler
{
public:
    ScriptableDevice( NPP npp );
    virtual ~ScriptableDevice();

    virtual bool construct( const NPVariant *args, uint32_t argCount, NPVariant *result );

    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );

    void setReference( const ImagingDevice* value ) { m_item = const_cast<ImagingDevice*>( value ); }

    virtual void disposed();

private:

    ImagingDevice* m_item;

    NPUTF8* m_id;
    NPUTF8* m_uid;
    NPUTF8* m_manufacturer;
    NPUTF8* m_productFamily;
    NPUTF8* m_productName;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptableDevice );


class ScriptableDeviceIndexer : public NPObjectBase
{
public:
    ScriptableDeviceIndexer( NPP npp );
    virtual ~ScriptableDeviceIndexer();

    virtual bool construct( const NPVariant *args, uint32_t argCount, NPVariant *result );

    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );
    virtual bool invoke( NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result );

    void setModel( PluginModel* value ) { m_model = value; }

private:

    List<NPIdentifier> m_npidList;
    PluginModel* m_model;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptableDeviceIndexer );


struct BaseCap;

class ScriptableDeviceCapability : public NPObjectBase
{
public:
    ScriptableDeviceCapability( NPP npp );
    virtual ~ScriptableDeviceCapability();

    virtual bool construct( const NPVariant *args, uint32_t argCount, NPVariant *result );

    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );

    void setReference( BaseCap* value ) { m_cap = value; }

private:

    NPObject* m_npoArray;

private:

    BaseCap* m_cap;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptableDeviceCapability );


class ScriptableImage : public NPObjectBase, public DisposeEventHandler
{
public:
    ScriptableImage( NPP npp );
    virtual ~ScriptableImage();

    virtual bool construct( const NPVariant *args, uint32_t argCount, NPVariant *result );

    virtual bool hasMethod( NPIdentifier name );
    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );
    virtual bool invoke( NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result );

    void setReference( const PluginImage* value ) { m_item = const_cast<PluginImage*>( value ); }

    virtual void disposed();

private:

    PluginImage* m_item;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptableImage );


class ScriptableImageIndexer : public NPObjectBase
{
public:
    ScriptableImageIndexer( NPP npp );
    virtual ~ScriptableImageIndexer();

    virtual bool construct( const NPVariant *args, uint32_t argCount, NPVariant *result );

    virtual bool hasMethod( NPIdentifier name );
    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );
    virtual bool invoke( NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result );

    void setModel( PluginModel* value ) { m_model = value; }

private:

    List<NPIdentifier> m_npidList;
    PluginModel* m_model;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptableImageIndexer );


class ScriptablePluginObject : public NPObjectBase
{
public:
    ScriptablePluginObject( NPP npp );
    virtual ~ScriptablePluginObject();

    virtual bool hasMethod( NPIdentifier name );
    virtual bool hasProperty( NPIdentifier name );
    virtual bool getProperty( NPIdentifier name, NPVariant *result );
    virtual bool setProperty( NPIdentifier name, const NPVariant *value );
    virtual bool invoke( NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result );
    //virtual bool invokeDefault( const NPVariant *args, uint32_t argCount, NPVariant *result );

    // events
    NPObject *m_npoOnScanComplete, 
        *m_npoOnImageAcquired, 
        *m_npoOnSaveComplete, 
        *m_npoOnSelectedImageChanged, 
        *m_npoOnImageCountChanged, 
        *m_npoOnDeviceEvent, 
        *m_npoOnZoomChange, 
        *m_npoOnToolStateChange, 
        *m_npoOnError;
#ifndef _ADDON
    NPObject *m_npoOnUploadComplete, 
        *m_npoOnUploadFailed;
#endif

    ScriptableDeviceIndexer* m_npoDeviceIndexer;
    ScriptableImageIndexer* m_npoImageIndexer;
};

DECLARE_NPOBJECT_CLASS_WITH_BASE( ScriptablePluginObject );


struct NPIds
{
    NPIdentifier scan, saveToFile, saveToArray;
#ifndef _ADDON
    NPIdentifier upload;
#endif
    NPIdentifier zoom, zoomTool, zoomIn, zoomOut, zoomReset, fitZoom;
    NPIdentifier panTool, pan, panX, panY, panOn, panOff;
    NPIdentifier cropTool, crop;
    NPIdentifier rotate;
    NPIdentifier documentCookie;
    NPIdentifier onScanComplete, onImageAcquired, onSelectedImageChanged, onSaveComplete, onImageCountChanged, onDeviceEvent, onZoomChanged, onToolStateChanged, onError;
#ifndef _ADDON
    NPIdentifier onUploadComplete, onUploadFailed;
#endif
    NPIdentifier pixelType, resolution, contrast, pageWidth, pageHeight, orientation;
    NPIdentifier transferMode;
    NPIdentifier getDevices, devices, deviceIndex, selectedDeviceId, deviceType, showDeviceUI;
    NPIdentifier manufacturer, productFamily, productName;
    NPIdentifier testMethod, testProperty;
    NPIdentifier id, uid, index, name;
    NPIdentifier driverModel;
    NPIdentifier selectImage, selectNextImage, selectPreviousImage, selectedIndex;
    NPIdentifier imageQuality;
    NPIdentifier autoPosition, autoCompress, autoCompressionLevel, autoCompressInBackground;
    NPIdentifier paperSource;
    NPIdentifier cap, type, valueType, count, value, item, values, items, min, max, step, defaultValue, currentValue, defaultIndex, currentIndex;
    NPIdentifier getCap;
    NPIdentifier connect, disconnect;
    NPIdentifier width, height;
    NPIdentifier current, images;
    NPIdentifier at, get;
    NPIdentifier getThumbnailUrl, getPixel, setPixel;
    NPIdentifier clear;
    NPIdentifier version;
    NPIdentifier getFilter, setFilter;
    NPIdentifier resume, autoPause, stop, pause;
    NPIdentifier thumbnailSize;
    NPIdentifier initializeDevice;
    NPIdentifier isFlatbedSupported, isFeederSupported, isDuplexSupported;
    NPIdentifier isConnected;
    NPIdentifier isPlatformSupported;
    NPIdentifier getFolder, openFolder;
    NPIdentifier focus;
    NPIdentifier deleteImage, shiftImage, moveImage;
    NPIdentifier getImageData, putImageData;

    // dom identifiers
    NPIdentifier document, location, href, push, pop, Array, constructor, length;
};

extern struct NPIds npid;


#define IS_NUMERIC( v ) ( NPVARIANT_IS_INT32( v ) || NPVARIANT_IS_DOUBLE( v ) )
#define AS_INT( v ) ( NPVARIANT_IS_INT32( v ) ? NPVARIANT_TO_INT32( v ) : ( NPVARIANT_IS_DOUBLE( v ) ?  ( int ) NPVARIANT_TO_DOUBLE( v ) : 0 ) )
